//引入express第三方模块
const express = require("express");
//创建路由器对象
const r = express.Router();
const svgCaptcha = require("svg-captcha"); //引入验证码依赖
const formidable = require("formidable"); //文件上传
const fs = require("fs");
const path = require("path");
//引入自带加密模块
const crypto = require("crypto");
var USER = null;

//引入连接数据库,不是中间件不能写在app.js中
const pool = require("../mysql.js");

//nodemailer.js
const nodemailer = require("nodemailer"); //发送邮件

//创建一个smtp服务器
const config = {
  host: "smtp.qq.com",
  port: 465,
  auth: {
    user: "", //你的qq邮箱账号
    pass: "", //邮箱的授权码，不是注册时的密码,等你开启的stmp服务自然就会知道了
  },
};
// 创建一个SMTP客户端对象
const transporter = nodemailer.createTransport(config);

//验证码
r.get("/captcha", (req, res) => {
  const captcha = svgCaptcha.create({
    inverse: false, // 翻转颜色
    noise: 3, // 噪声线条数
    width: 80,
    height: 30,
    color: "#ff0ff0",
    background: "#F1F3F4",
    fontSize: 35,
  });
  // 保存到sess
  req.sess = captcha.text;
  console.log(req.sess); //0xtg 生成的验证码

  res.send({
    img: captcha.data,
    text: req.sess,
  });
});

//登陆
r.post("/login", (req, res, next) => {
  let md5 = crypto.createHash("md5"); //创建md5加密
  req.body.password = md5.update(req.body.password).digest("hex"); //加密传过来的密码
  pool.query(
    "select * from user where (username=? or email=?)  and password=? and type=?",
    [
      req.body.username,
      req.body.username,
      req.body.password,
      req.body.usertype,
    ],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result[0].type);

      //结果是数组，如果是空数组，提示查无此人，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "账号或密码错误",
        });
      } else {
        pool.query(
          "select username from user where (username=? or email=?)",
          [req.body.username, req.body.username],
          (err, result) => {
            if (err) {
              next(err);
              return;
            }
            // console.log(result[0].username);
            if (result.length == 0) {
              res.send({
                status: 201,
                msg: "账号或密码错误",
              });
            } else {
              //为避免用户用邮箱登录时用户名会显示为邮箱，所以应该把用户名查出来
              // req.session.username = result[0].usernameusername;
              res.cookie(
                "userinfo",
                {
                  username: result[0].username,
                },
                {
                  maxAge: 1000 * 60 * 60 * 12,
                }
              );
              USER = result[0].username; //后面上传头像使用
              res.send({
                status: 200,
                msg: "登陆成功",
                utype: req.body.usertype,
                uname: result[0].username,
              });
            }
          }
        );
      }
      pool.releaseConnection(pool);
    }
  );
});

//退出登陆
r.get("/logout", (req, res, next) => {
  res.clearCookie("userinfo"); //退出登陆登陆删除cookie
});

//注册
r.post("/register", (req, res, next) => {
  let md5 = crypto.createHash("md5"); //创建md5加密
  req.body.password = md5.update(req.body.password).digest("hex"); //加密传过来的密码
  // pool.query('insert into user set ?',[req.body],(err,result)=>{}) 这条语句是插入传过来的整个req.body对象，里面包含用户名密码...
  pool.query("insert into user set ?", [req.body], (err, result) => {
    //如果用form表单的action req.body,存储的是表单name里的值
    //err可能产生的错误,如果出现错误
    if (err) {
      next(err); //抛给下一个中间件来处理
      //阻止往后执行
      return;
    }
    //console.log(result)
    res.send({
      status: 200,
      msg: "注册成功",
    });
  });
  pool.releaseConnection(pool);
});

//发送邮箱生成验证码
r.get("/email", (req, res, next) => {
  var code = createSixNum(); //生成验证码
  function createSixNum() {
    var Num = "";
    for (var i = 0; i < 6; i++) {
      Num += Math.floor(Math.random() * 10);
    }
    return Num;
  }

  var mail = {
    // 发件人
    from: "<2324094523@qq.com>",
    // 主题
    subject: "验证码", //邮箱主题
    // 收件人
    to: req.query.email, //前台传过来的邮箱
    // 邮件内容，HTML格式
    //text: '验证码:' + code //发送验证码
    html: `
		     <p>你好！</p>
		     <p>您正在注册在线考试系统账号</p>
		     <p>你的验证码是：<strong style="color: #ff4e2a;">${code}</strong></p>
		     <p>***该验证码5分钟内有效***</p>`, // html 内容
  };
  transporter.sendMail(mail, function (error, info) {
    if (error) {
      return console.log(error);
    }
    console.log("mail sent:", info.response);
  });

  //把验证码，邮箱传入yzm表 为了模拟验证码有效期
  pool.query(
    "insert into yzm (code,email) values(?,?)",
    [code, req.query.email],
    (err, result) => {
      //err可能产生的错误,如果出现错误
      if (err) {
        next(err); //抛给下一个中间件来处理
        //阻止往后执行
        return;
      }
      //console.log(result)
      res.send({
        status: 200,
      });
    }
  );

  //模拟验证码有效期 5分钟后删除该验证码
  setTimeout(() => {
    pool.query(
      "delete  from yzm where email=?",
      [req.query.email],
      (err, result) => {
        //err可能产生的错误,如果出现错误
        if (err) {
          next(err); //抛给下一个中间件来处理
          //阻止往后执行
          return;
        }

        //console.log(result)
        if (result.affectedRows == 0) {
          console.log("删除失败");
        } else {
          console.log("删除成功");
        }
      }
    );
  }, 1000 * 60 * 5);
  pool.releaseConnection(pool);
});

//获取验证码
r.get("/emailyzm", (req, res, next) => {
  //按升序排序，取最后一条验证码
  pool.query(
    "select code,y_id from yzm where email=? order by y_id ASC",
    [req.query.email],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查询失败
      if (result.length == 0) {
        console.log("查询失败");
        res.send({
          status: 201,
          msg: "查询失败",
        });
      } else {
        //用户可能多次发送，所以应该发送最后一条数据
        res.send({
          status: 200,
          data: result[result.length - 1].code,
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//忘记密码
r.put("/forgetpassword", (req, res, next) => {
  let obj = req.body;
  let md5 = crypto.createHash("md5"); //创建md5加密
  obj.password = md5.update(obj.password).digest("hex"); //加密传过来的密码
  pool.query(
    "update user set password=? where email=?",
    [obj.password, obj.email],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      if (result.affectedRows == 0) {
        res.send({
          status: 201,
          msg: "修改失败",
        });
      } else {
        res.send({
          status: 200,
          msg: "修改成功",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//上传头像1
r.post("/updateicon", (req, res, next) => {
  pool.query(
    "select url from user where username=?",
    [req.cookies.userinfo.username],
    (err, result) => {
      //登陆成功后以cookie查询用户头像地址
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查询失败，否则删除当前的头像
      if (result.length == 0) {
        console.log("查询失败");
        res.send({
          status: 201,
          msg: "查询失败",
        });
      } else {
        if (result[0].url != "/uploads/touxiang.png") {
          fs.unlinkSync(path.join(__dirname, "../public") + result[0].url);
        }
      }
    }
  );

  var form = new formidable.IncomingForm();
  // 设置要上传的位置
  form.uploadDir = path.join(__dirname, "../public/uploads");
  // console.log(req)
  form.parse(req);

  form.on("end", function () {
    console.log("success");
  });

  form.on("file", (field, file) => {
    let timestamp = Date.parse(new Date()); //使用时间戳
    let name = timestamp.toString() + file.name; //时间戳转化为字符串加上文件名重新给文件命名
    /*********此行代码一定要加入，就是给文件改名字***********/
    fs.renameSync(file.path, path.join(form.uploadDir, name)); //把name传入
    //path.join中的file是回调函数中的file
    //改完名字以后，把相应的路径存放到数据库。
    //要存放到数据库，就要连接数据库
    let str = "/uploads/";
    name = str + name; //拼接传入数据库的路径和文件名，使数据库的路径和图片文件路径和名称一致
    pool.query(
      "update user set url=? where username=?",
      [name, USER],
      (err, result) => {
        if (err) {
          next(err);
          return;
        }
        //console.log(result);
        if (result.affectedRows == 0) {
          res.send({
            status: 201,
            msg: "修改失败",
          });
        } else {
          res.send({
            status: 200,
            msg: "修改成功",
          });
        }
      }
    );
    pool.releaseConnection(pool);
  });
});

//上传头像2
r.put("/updateicon2", (req, res, next) => {
  pool.query(
    "select url from user where username=?",
    [req.cookies.userinfo.username],
    (err, result) => {
      //登陆成功后以cookie查询用户头像地址
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查询失败，否则删除当前的头像
      if (result.length == 0) {
        console.log("查询失败");
        res.send({
          status: 201,
          msg: "查询失败",
        });
      } else {
        if (result[0].url != "/uploads/touxiang.png") {
          fs.unlinkSync(path.join(__dirname, "../public") + result[0].url); //删除图片
        }
      }
    }
  );

  //接收前台put过来的base64
  var imgData = req.body.imgData;
  //过滤data:URL
  var base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
  var timestamp = Date.parse(new Date());
  var dataBuffer = Buffer.from(base64Data, "base64");
  var name = timestamp.toString() + ".jpg";
  // 写入的地址
  fs.writeFile("./public/uploads/" + name, dataBuffer, function (err) {
    if (err) {
      console.log(err);
    } else {
      console.log("服务端接收到了数据啦");
    }
  });
  let str = "/uploads/";
  name = str + name;
  //path.join中的file是回调函数中的file
  //改完名字以后，把相应的路径存放到数据库。
  //要存放到数据库，就要连接数据库
  pool.query(
    "update user set url=? where username=?",
    [name, USER],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      if (result.affectedRows == 0) {
        res.send({
          status: 201,
          msg: "修改失败",
        });
      } else {
        res.send({
          status: 200,
          msg: "修改成功",
          data: name,
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//修改密码
r.put("/updatepassword", (req, res, next) => {
  // console.log(req.cookies.userinfo)
  let md5 = crypto.createHash("md5"); //创建md5加密
  //req.body.password = md5.update(req.body.password).digest("hex"); //加密传过来的原密码
  //Error [ERR_CRYPTO_HASH_FINALIZED]: Digest already called
  //hash实例调用digest之后不能再调用update
  //req.body.newpassword=md5.update(req.body.newpassword).digest("hex");//加密传递过来的新密码
  //解决
  req.body.password = md5.update(req.body.password).digest("hex");
  let md52 = crypto.createHash("md5");
  req.body.newpassword = md52.update(req.body.newpassword).digest("hex");
  //先用原密码查看是否有这个用户
  pool.query(
    "select uid from user where password=? and username=?",
    [req.body.password, req.cookies.userinfo.username],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查询失败
      if (result.length == 0) {
        console.log("查询失败");
        res.send({
          status: 201,
          msg: "查询失败",
        });
      } else if (req.body.password != req.body.newpassword) {
        pool.query(
          "update user set password=? where username=?",
          [req.body.newpassword, req.cookies.userinfo.username],
          (err, result) => {
            if (err) {
              next(err);
              return;
            }
            // console.log(result);
            if (result.affectedRows == 0) {
              res.send({
                status: 201,
                msg: "修改失败",
              });
            } else {
              res.send({
                status: 200,
                msg: "修改成功",
              });
            }
          }
        );
      } else {
        res.send({
          status: 201,
          msg: "修改失败",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//用户名是否已存在
r.post("/checkname", (req, res, next) => {
  pool.query(
    "select * from user where username=?",
    [req.body.username],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查无此人，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "该用户名不存在",
        });
      } else {
        res.send({
          status: 200,
          msg: "该用户名已存在",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//手机号是否已存在
r.post("/checkphone", (req, res, next) => {
  pool.query(
    "select * from user where phone=?",
    [req.body.phone],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查无此人，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "该手机号不存在",
        });
      } else {
        res.send({
          status: 200,
          msg: "该手机号已存在",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//邮箱是否已存在
r.post("/checkemail", (req, res, next) => {
  pool.query(
    "select * from user where email=?",
    [req.body.email],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查无此人，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "该邮箱不存在",
        });
      } else {
        res.send({
          status: 200,
          msg: "该邮箱已存在",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//密码是否已存在
r.post("/checkpassword", (req, res, next) => {
  let md5 = crypto.createHash("md5"); //创建md5加密
  req.body.password = md5.update(req.body.password).digest("hex"); //加密传过来的密码
  pool.query(
    "select uid from user where password=? and username=?",
    [req.body.password, req.cookies.userinfo.username],
    (err, result) => {
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查无此人，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "密码不存在",
        });
      } else {
        res.send({
          status: 200,
          msg: "密码正确",
        });
      }
    }
  );
  pool.releaseConnection(pool);
});

//更新头像
r.get("/searchicon", (req, res, next) => {
  pool.query(
    "select url from user where username=?",
    [req.cookies.userinfo.username],
    (err, result) => {
      //登陆成功后以cookie查询用户头像地址
      if (err) {
        next(err);
        return;
      }
      //console.log(result);
      //结果是数组，如果是空数组，提示查询失败，否则查询成功
      if (result.length == 0) {
        res.send({
          status: 201,
          msg: "查询失败",
        });
      } else {
        res.send({
          status: 200,
          msg: "查询成功",
          data: result,
        }); //发送地址
      }
    }
  );
  pool.releaseConnection(pool);
});

//导出路由器对象
module.exports = r;
